﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;

namespace EasyStep.Business
{
    public static class ObjectManager
    {
        public static IUnityContainer Container;

        public static void Initialize()
        {
            Initialize(null);
        }

        public static void Initialize(IUnityContainer container)
        {
            if (container != null) Container = container;
            else
            {
                Container = Container != null ? Container : new UnityContainer();
            }
        }

        public static void RegisterInstance<IServiceInterface, TServiceImplementation>()
            where TServiceImplementation : IServiceInterface, new()
        {
            Container.RegisterInstance<IServiceInterface>(new TServiceImplementation());
        }
        public static void RegisterInstance<TService>(Func<TService> onGetInstance, string name = null)
        {
            RegisterInstance<TService>(onGetInstance(), name);
        }

        public static void RegisterInstance<TService>(TService Instance, string name = null)
        {
            if (String.IsNullOrEmpty(name))
                Container.RegisterInstance<TService>(Instance);
            else
                Container.RegisterInstance<TService>(name,Instance);
        }

        public static void RegisterInstance<IServiceInterface, TServiceImplementation>(string name)
            where TServiceImplementation : IServiceInterface, new()
        {
            if (String.IsNullOrEmpty(name))
                throw new NullReferenceException("Name is not specified for named registration.");

            Container.RegisterInstance<IServiceInterface>(name, new TServiceImplementation());
        }

        public static void RegisterInstanceWithConstructorParams<IServiceInterface, TServiceImplementation>(params object[] paramValues)
            where TServiceImplementation : IServiceInterface, new()
        {
            Container.RegisterInstance<IServiceInterface>(new TServiceImplementation())
                .Configure<InjectedMembers>()
                .ConfigureInjectionFor<TServiceImplementation>(new InjectionMember[] { new InjectionConstructor(paramValues) });
        }

        public static void RegisterType<TServiceImplementation>()
        {
            Container.RegisterType<TServiceImplementation>(new TransientLifetimeManager());
        }
        public static void RegisterType(string name,Type IServiceInterface, Type TServiceImplementation)          
        {
            if (String.IsNullOrEmpty(name))
                throw new NullReferenceException("Name is not specified for named registration.");

            Container.RegisterType(IServiceInterface,TServiceImplementation,name, new TransientLifetimeManager());///todo:check lifetime manager?
         
            
        }
        public static IServiceInterface GetInstance<IServiceInterface>(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new NullReferenceException("Name is not specified for named registration.");

            return Container.IsRegistered<IServiceInterface>(name) ? Container.Resolve<IServiceInterface>(name) : default(IServiceInterface);
        }

        public static IServiceInterface GetInstance<IServiceInterface>()
        {
            return Container.IsRegistered<IServiceInterface>() ? Container.Resolve<IServiceInterface>() : default(IServiceInterface);
        }

        public static object GetInstanceAsObject(Type serviceType)
        {
            return Container.IsRegistered(serviceType) ? Container.Resolve(serviceType) : null;
        }

        public static IEnumerable<IServiceInterface> GetInstances<IServiceInterface>()
        {
            return Container==null?null:Container.ResolveAll<IServiceInterface>();
        }

        public static IEnumerable<object> GetInstancesAsObjects(Type serviceType)
        {
            return Container.IsRegistered(serviceType) ? Container.ResolveAll(serviceType) : new List<object>();
        }

        public static bool IsRegistered(Type serviceType)
        {
            return Container.IsRegistered(serviceType);
        }
        public static IEnumerable<Type>  GetRegistration(Type ForType, string name=null)
        {
            var result=Container.Registrations.Where(r=>r.RegisteredType.Equals(ForType));
            if(!string.IsNullOrEmpty(name))
                result= result.Where(r=>!string.IsNullOrEmpty(r.Name)&&  r.Name.Equals(name));
            return result.Select(r => r.MappedToType);
        }
    }
}